# -*- coding: utf-8 -*-

#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.

#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.

#You should have received a copy of the GNU General Public License
#along with this program.  If not, see <http://www.gnu.org/licenses/>.

import wx
import wx.grid
import CDDB, DiscID, os, re
import time,filecmp
import subprocess as sub
from copy import copy
import cPickle as cp

class Config(object):
    def __init__(self):
	self.encoder = 'lame'
	self.encoder_opts = '-V 0 --vbr-new --add-id3v2'
	self.file_fmt = '[a] - [n] [t]'
	self.device = '/dev/cdrom'
	self.strip_special = False
	self.eject_after = 1
	self.open_folder = False
	self.basedir = os.path.join(os.environ.get('HOME'),'Music')
	self.logfile = 1
	self.nscans = 2
	self.nrescans = 8
	self.offset = 0


class TrackList(wx.Panel):
    CONFIG = Config()
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
	sizer = wx.FlexGridSizer(2,1,0,0)
        sizer0 = wx.FlexGridSizer(1,2,0,0)

	sizer3 = self._MakeHeader(parent)

	parent.__setattr__('grid',self._MakeGrid())
	gbox = wx.StaticBox(self, -1,'Track List')
	sizer1 = wx.StaticBoxSizer(gbox,wx.VERTICAL)
	sizer1.Add(parent.grid, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)

	buttons = self._MakeButtons(parent)
	bbox = wx.StaticBox(self, -1,'Functions')
	sizer2 = wx.StaticBoxSizer(bbox,wx.VERTICAL)
	sizer2.Add(buttons, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)

	sizer0.Add(sizer1,0,wx.ALL,5) # row1, col1
	sizer0.Add(sizer2,0,wx.ALL,5) # row1, col1
	#border = wx.BoxSizer()
	#border.Add(sizer0, 0, wx.ALL, 0)
	sizer.Add(sizer3, 0, wx.ALL, 10)
	sizer.Add(sizer0, 0 , wx.ALL, 10)
	self.SetSizerAndFit(sizer)
	self.Fit()

    def _MakeGrid(self):
	grid = wx.grid.Grid(self)
        grid.CreateGrid(15,2)
	attr = wx.grid.GridCellAttr()
	attr.SetReadOnly(True)
	grid.SetColAttr(0, attr)
	#grid.SetColAttr(2, attr)
	grid.SetColAttr(1, attr)
	grid.SetColLabelValue(0, "Track Name")
	grid.SetColLabelValue(1, "Length")
	grid.SetColSize(0,255)
	grid.SetColSize(1,80)
	grid.SetRowLabelSize(40)
	grid.SetCellBackgroundColour(14,1,wx.BLACK)
	grid.SetCellTextColour(14,1,wx.WHITE)
        for row in range(15):
            grid.SetCellValue(row, 0,'Track %d' % (row+1))
            for col in range(2):
		if row%2 == 0:
		    grid.SetCellBackgroundColour(row,col,wx.Colour(15,15,45))
		    grid.SetCellTextColour(row,col,wx.WHITE)
		else:
		    grid.SetCellBackgroundColour(row,col,wx.WHITE)
		    grid.SetCellTextColour(row,col,wx.BLACK)
	#for i in dir(grid): 
	    #if 'Colour' in i: print i
	grid.SetMinSize((400,400))
	return grid

    def _MakeButtons(self,parent):
	bsz = (80,50)
	box = wx.BoxSizer(wx.VERTICAL)
	parent.__setattr__('query',wx.Button(self,-1,'Query'))
	parent.query.SetMinSize(bsz)
	box.Add(parent.query, 0, wx.ALL, 5)
	parent.__setattr__('extract',wx.ToggleButton(self,-1,'Extract'))
	parent.extract.SetMinSize(bsz)
	box.Add(parent.extract, 0, wx.ALL, 5)
	parent.__setattr__('configure',wx.ToggleButton(self,-1,'Configure'))
	parent.configure.SetMinSize(bsz)
	box.Add(parent.configure, 0, wx.ALL, 5)
	parent.__setattr__('eject',wx.Button(self,-1,'Eject'))
	parent.eject.SetMinSize(bsz)
	box.Add(parent.eject, 0, wx.ALL, 5)
	return box

    def _MakeHeader(self,parent):
	txtcolor = wx.Colour(0,80,80)
	box = wx.BoxSizer(wx.VERTICAL)
	sizera = wx.FlexGridSizer(1,4,0,0)
	sizerb = wx.FlexGridSizer(1,6,0,0)
	sizerc = wx.FlexGridSizer(1,2,0,0)

	artisttxt = wx.StaticText(self,-1,'Artist:')
	artist = wx.TextCtrl(self,-1,'')
	artist.SetMinSize((305,27))
	artist.SetForegroundColour(txtcolor)
	parent.__setattr__('artist',artist)
	genretxt = wx.StaticText(self,-1,'Genre: ')
	genre = wx.TextCtrl(self,-1,'')
	genre.SetMinSize((85,27))
	genre.SetForegroundColour(txtcolor)
	parent.__setattr__('genre',genre)
	sizera.Add(artisttxt, 0, wx.ALL, 5)
	sizera.Add(artist, 0, wx.RIGHT|wx.ADJUST_MINSIZE, 10)
	sizera.Add(genretxt, 0, wx.ALL, 5)
	sizera.Add(genre, 0, wx.ALL|wx.ADJUST_MINSIZE, 0)

	titletxt = wx.StaticText(self,-1,'Title:  ')
	title = wx.TextCtrl(self,-1,'')
	title.SetMinSize((255,27))
	title.SetForegroundColour(txtcolor)
	parent.__setattr__('title',title)
	sizerb.Add(titletxt, 0, wx.ALL, 5)
	sizerb.Add(title, 0, wx.RIGHT|wx.ADJUST_MINSIZE, 10)
	yeartxt = wx.StaticText(self,-1,'Year:   ')
	year = wx.TextCtrl(self,-1,'')
	year.SetMinSize((45,27))
	year.SetForegroundColour(txtcolor)
	parent.__setattr__('year',year)
	sizerb.Add(yeartxt, 0, wx.ALL, 5)
	sizerb.Add(year, 0, wx.RIGHT|wx.ADJUST_MINSIZE, 10)
	disctxt = wx.StaticText(self,-1,'Disc:   ')
	disc = wx.TextCtrl(self,-1,'')
	parent.__setattr__('disc',disc)
	disc.SetMinSize((25,27))
	disc.SetForegroundColour(txtcolor)
	sizerb.Add(disctxt, 0, wx.ALL, 5)
	sizerb.Add(disc, 0, wx.RIGHT|wx.ADJUST_MINSIZE, 10)

	box.Add(sizera, 0, wx.ALL, 5)
	box.Add(sizerb, 0, wx.ALL, 5)
	return box

class PageTwo(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        t = wx.StaticText(self, -1, "This is a PageTwo object", (40,40))

class PageThree(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        t = wx.StaticText(self, -1, "This is a PageThree object", (60,60))


class MainFrame(wx.Frame):
    DISCID = None
    #CONFIG = CONFIG
    def __init__(self):
        wx.Frame.__init__(self, None, title="DXV",size=(580,600))
	self._CreateMenu()
	self.__setattr__('CONFIG',Config())
	
	try:
	    cdrom = DiscID.open()
	    #print dir(cdrom)
	    disc_id = DiscID.disc_id(cdrom)
	    #print dir(disc_id),disc_id
	    self.DISCID = disc_id
	except: self.DISCID = None

        ## create the page windows as children of the notebook
        page1 = TrackList(self)
	self.query.Bind(wx.EVT_BUTTON,self.QUERY)
	self.extract.Bind(wx.EVT_TOGGLEBUTTON,self.EXTRACT)
	self.configure.Bind(wx.EVT_TOGGLEBUTTON,self.CONFIGURE)
	self.eject.Bind(wx.EVT_BUTTON,self.EJECT)

        #page2 = PageTwo(nb)

        sizer = wx.BoxSizer()
        sizer.Add(page1, 1, wx.EXPAND)
        self.SetSizer(sizer)
	self.sb = self.CreateStatusBar()
	self.Fit()
	self.configure_menu = ConfigureMenu(self)
	#self.configure_menu.Hide()
	if 'DxV.config' in os.listdir('./'):
	    fh = open('DxV.config','r')
	    self.CONFIG = cp.load(fh)
	    self.configure_menu.SetConfig(self.CONFIG)
	else:
	    self.CONFIG = Config() ### fix this

    def _CreateMenu(self):
	menubar = wx.MenuBar()
	filemenu = wx.Menu()
	filemenu.Append(101, 'Query &FreeDB\tCtrl+F', 'Retrieve Disc Info')
	filemenu.Append(102, '&Eject\tCtrl+E', 'Eject the Disc')
	filemenu.Append(103, 'E&xtract\tCtrl+X', 'Rip Audio')
	filemenu.AppendSeparator()
	config = wx.MenuItem(filemenu, 104, '&Configure\tCtrl+C', 'Configure the Application')
	filemenu.AppendItem(config)
	filemenu.AppendSeparator()
	quit = wx.MenuItem(filemenu, 105, '&Quit\tCtrl+Q', 'Quit the Application')
	#quit.SetBitmap(wx.Image('stock_exit-16.png',wx.BITMAP_TYPE_PNG).ConvertToBitmap())
	filemenu.AppendItem(quit)
	menubar.Append(filemenu, '&File')
	self.SetMenuBar(menubar)
	wx.EVT_MENU(self, 101, self.QUERY )
	wx.EVT_MENU(self, 102, self.EJECT )
	wx.EVT_MENU(self, 103, self.EXTRACT )
	wx.EVT_MENU(self, 105, self.OnQuit )

    def OnQuit(self, event): self.Close()

    def QUERY(self,event):
	self.sb.SetStatusText('Querying FreeDB for Disc Info...')
	cdrom = DiscID.open()
	disc_id = DiscID.disc_id(cdrom)
	self.DISCID = disc_id

	query_status, query_info = CDDB.query(disc_id)
	try: (read_status, read_info) = CDDB.read(query_info[0]['category'], query_info[0]['disc_id'])
	except: (read_status, read_info) = CDDB.read(query_info['category'], query_info['disc_id'])
	self.year.SetValue(read_info['DYEAR'])
	self.genre.SetValue(read_info['DGENRE'])
	dtitle = read_info['DTITLE']
	try: artist, title = dtitle.split('/')
	except: artist, title = '', dtitle
	self.title.SetValue(title.strip().decode('latin-1'))
	self.artist.SetValue(artist.strip().decode('latin-1'))
	nrows = self.grid.GetNumberRows()
	self.grid.ClearGrid()
	track_len = self.CalcLen(disc_id)
	if nrows < disc_id[1]: self.grid.InsertRows(nrows,disc_id[1] - nrows)
        for i in range(disc_id[1]):
	    if i%2 == 0:
		self.grid.SetCellBackgroundColour(i,0,wx.Colour(15,15,45))
		self.grid.SetCellTextColour(i,0,wx.WHITE)
		self.grid.SetCellBackgroundColour(i,1,wx.Colour(15,15,45))
		self.grid.SetCellTextColour(i,1,wx.WHITE)
	    else:
		self.grid.SetCellBackgroundColour(i,0,wx.WHITE)
		self.grid.SetCellTextColour(i,0,wx.BLACK)
		self.grid.SetCellBackgroundColour(i,1,wx.WHITE)
		self.grid.SetCellTextColour(i,1,wx.BLACK)

	    self.grid.SetCellValue(i,0,'%s' % (read_info['TTITLE' + `i`].decode('latin-1')))
	    minutes = int(round(track_len[i]))/60
	    seconds = int(round(track_len[i]))%60
	    if seconds < 10: trlen = '%d:0%d'%(minutes,seconds)
	    else:  trlen = '%d:%d'%(minutes,seconds)
	    self.grid.SetCellValue(i,1,trlen)
	self.sb.SetStatusText('')

    def EXTRACT(self,event):
	if hasattr(self,'extract_menu'):
	    if self.extract.GetValue(): self.extract_menu.Show()
	    else: self.extract_menu.Hide()
	else: self.extract_menu = ExtractMenu(self)

    def CONFIGURE(self,event):
	if hasattr(self,'configure_menu'):
	    if self.configure.GetValue(): self.configure_menu.Show()
	    else: self.configure_menu.Hide()
	else: self.configure_menu = ConfigureMenu(self)

    def CalcLen(self,disc_id):
	tracks = disc_id[2:-1]
	total_len = disc_id[-1]
	track_len = []
	cnv = 0.01326
	calc_total = 0
	for i,j in enumerate(tracks):
	    if i+1 != len(tracks):
		length = (tracks[i+1]-tracks[i])*cnv
		calc_total += length
		track_len.append(length)
	    else:
		track_len.append(total_len - calc_total)
	return track_len

    def EJECT(self, *args):
	self.sb.SetStatusText('Ejecting Disc...')
	os.system("eject")
	self.sb.SetStatusText('')



class ExtractMain(wx.Panel):
    DISCID = None
    extracted = []
    toencode = []
    #OFFSET = 0
    def __init__(self, nb, parent):
        wx.Panel.__init__(self, nb)
	#print self.GetWindowStyle()
	#self.SetWindowStyle(self.GetWindowStyle() & ~ (wx.RESIZE_BORDER|wx.RESIZE_BOX|wx.MAXIMIZE_BOX|wx.CLOSE_BOX))
	#print self.GetWindowStyle()

	self.parent = parent
	self.LoadTracks(None)

	sizer = wx.FlexGridSizer(2,3,0,0)
	chbox = wx.FlexGridSizer(15,2,0,0)
	trbox = wx.StaticBox(self, -1,'Track Selection')
	sizer1 = wx.StaticBoxSizer(trbox,wx.VERTICAL)
	trbox.SetMinSize((180,425))
	tracks = []
	for i in range(self.ntracks):
	    exec 'self.track%d = wx.CheckBox(self, -1, \'Track %d \')'%(i+1,i+1)
	    exec 'self.track%d.SetValue(True)'%(i+1)
	    exec 'chbox.Add(self.track%d,0,wx.ALL,2)'%(i+1)
	sizer1.Add(chbox, 0, wx.ALL, 2)

	self.multi = wx.TextCtrl(self, -1, style = wx.TE_MULTILINE|wx.TE_READONLY )
	self.multi.SetMinSize((400,400))
	mbox = wx.StaticBox(self, -1,'Status')
	sizer2 = wx.StaticBoxSizer(mbox,wx.VERTICAL)
	sizer2.Add(self.multi, 0, wx.ADJUST_MINSIZE, 0)

	self.errorlist = wx.ListBox(self, -1)
	self.errorlist.Append('Word')
	self.errorlist.SetMinSize((200,400))
	lbox = wx.StaticBox(self, -1,'Errors')
	sizer3 = wx.StaticBoxSizer(lbox,wx.VERTICAL)
	sizer3.Add(self.errorlist, 0, wx.ADJUST_MINSIZE, 0)

	sizer4,sizer5,sizer6 = self._MakeButtons()

	sizer.Add(sizer1, 0, wx.ALL, 2)
	sizer.Add(sizer2, 0, wx.ALL, 2)
	sizer.Add(sizer3, 0, wx.ALL, 2)
	sizer.Add(sizer4, 0, wx.ALL|wx.ALIGN_CENTRE, 2)
	sizer.Add(sizer5, 0, wx.ALL|wx.ALIGN_CENTRE, 2)
	sizer.Add(sizer6, 0, wx.ALL|wx.ALIGN_CENTRE, 2)
	self.SetSizerAndFit(sizer)
	self.Fit()

	self.TIMER_ID = 100
	self.timer = wx.Timer(self, self.TIMER_ID)
	wx.EVT_TIMER(self, self.TIMER_ID, self.OnTimer)


    def _MakeButtons(self):
	self.all0 = wx.Button(self, -1, 'All')
	self.all0.SetMinSize((50,37))
	self.none0 = wx.Button(self, -1, 'None')
	self.none0.SetMinSize((50,37))
	self.reload0 = wx.Button(self, -1, 'Reload')
	self.reload0.SetMinSize((60,37))
	lbox = wx.BoxSizer(wx.HORIZONTAL)
	lbox.Add(self.all0, 0, wx.ALL, 5)
	lbox.Add(self.none0, 0, wx.ALL, 5)
	lbox.Add(self.reload0, 0, wx.ALL, 5)
	self.all0.Bind(wx.EVT_BUTTON, self.SelectAll)
	self.none0.Bind(wx.EVT_BUTTON, self.SelectNone)
	self.reload0.Bind(wx.EVT_BUTTON, self.LoadTracks)

	self.start = wx.Button(self, -1, 'Start')
	self.start.SetMinSize((50,37))
	self.stop = wx.Button(self, -1, 'Stop')
	self.stop.SetMinSize((50,37))
	self.gauge = wx.Gauge(self, -1, 100)
	#self.close = wx.Button(self, -1, 'Close')
	#self.close.SetMinSize((50,37))
	self.gauge.SetMinSize((150,37))
	self.gauge.SetValue(0)
	self.trackprog = wx.StaticText(self, -1, '(0 / %d)'%self.ntracks)
	cbox = wx.BoxSizer(wx.HORIZONTAL)
	cbox.Add(self.start, 0, wx.ALL, 5)
	cbox.Add(self.stop, 0, wx.ALL, 5)
	cbox.Add(self.gauge, 0, wx.ALL, 5)
	cbox.Add(self.trackprog, 0, wx.ALL, 15)
	self.start.Bind(wx.EVT_BUTTON, self.Start)
	self.stop.Bind(wx.EVT_BUTTON, self.Halt)
	#self.close.Bind(wx.EVT_BUTTON, self.Close)

	self.analyze = wx.Button(self, -1, 'Analyze')
	self.analyze.SetMinSize((75,37))
	rbox = wx.BoxSizer(wx.HORIZONTAL)
	rbox.Add(self.analyze, 0, wx.ALL, 5)

	return lbox,cbox,rbox

    def SelectAll(self,event):
	for i in range(self.ntracks): exec 'self.track%d.SetValue(True)'%(i+1)

    def SelectNone(self,event):
	for i in range(self.ntracks): exec 'self.track%d.SetValue(False)'%(i+1)

    def LoadTracks(self,event):
	try:
	    cdrom = DiscID.open()
	    disc_id = DiscID.disc_id(cdrom)
	    self.DISCID = disc_id
	    self.ntracks = disc_id[1]
	except:
	    self.DISCID = None
	    disc_id = []
	    self.ntracks = 2

    def Start(self,event):
	self.extract = []
	self.status = 'extract'
	self.p = None
	for i in range(self.ntracks): exec 'if self.track%d.GetValue(): self.extract.append(%d)'%((i+1),(i+1))
	path = self.parent.CONFIG.basedir
	for i in os.listdir(path):
	    if i[0:4] == 'temp' and os.path.splitext(i)[1] == '.wav':
		print 'moving %s'%i
		filename = os.path.join(path,i)
		os.system('mv %s %s.bak'%(filename,filename))
	self.extract = self.parent.CONFIG.nscans*self.extract
	self.extract.sort()
	#print self.extract
	self.ExtractDisable()
	self.__setattr__('p',None)
	self.__setattr__('curtrk',0)
	self.timer.Start(250)

    def ExtractEnable(self):
	for i in range(self.ntracks): exec 'self.track%d.Enable()'%(i+1)
	self.start.Enable()

    def ExtractDisable(self):
	for i in range(self.ntracks): exec 'self.track%d.Disable()'%(i+1)
	self.start.Disable()

    def Extract(self,trackno):
	path = self.parent.CONFIG.basedir
	if not os.path.exists(path): os.makedirs(path)
	tmpfile = 'temp%d_0.wav'%trackno
	extrano = 0
	while os.path.exists(os.path.join(path,tmpfile)): 
	    extrano += 1
	    tmpfile = 'temp%d_%d.wav'%(trackno,extrano)
	filename = os.path.join(path,tmpfile)
	self.extracted.append(tmpfile)
	self.multi.AppendText('Extracting Track %d, Scan %d\n'%(trackno,extrano))
	self.p = sub.Popen(['cdparanoia', str(trackno),'-O',str(self.parent.CONFIG.offset),filename],-1,shell=False)

    def OnTimer(self,event):
	if self.status == 'extract':
	    if hasattr(self.p,'poll') and self.p.poll() == None: pass
	    elif self.CheckTemps(self.curtrk): self.status = 'analyze'
	    elif len(self.extract) > 0:
		self.curtrk = self.extract.pop(0)
		self.Extract(self.curtrk)
	    else:
		self.Halt(None)
		if self.parent.CONFIG.logfile: self.WriteLog()
	elif self.status == 'analyze':
	    self.Compare(self.curtrk)
	    self.status = 'compress'
	elif self.status == 'compress':
	    #if len(self.toencode) > 0:
	    if hasattr(self.p,'poll'):
		if self.p.poll() == None: pass
		else: self.p = None
	    elif len(self.toencode) > 0: self.Encode()
	    else:
		self.RemoveTemps(self.curtrk)
		self.status = 'extract'

    def Compare(self,trackno):
	endfile = 'temp%d_%d.wav'%(trackno,self.parent.CONFIG.nscans-1)
	if endfile in self.extracted:
	    path = self.parent.CONFIG.basedir
	    same = True
	    if self.parent.CONFIG.nscans > 1:
		self.multi.AppendText('Analyzing Track %d\n'%trackno)
		for i in range(self.parent.CONFIG.nscans-1):
		    file1 = os.path.join(path,'temp%d_%d.wav'%(trackno,i))
		    file2 = os.path.join(path,'temp%d_%d.wav'%(trackno,i+1))
		    self.multi.AppendText('  Comparing Extraction %d and %d\n'%(i,i+1))
		    res = filecmp.cmp(file1,file2)
		    if res == False:
			same = False
			self.multi.AppendText('  Difference detected between %d and %d\n'%(i,i+1))
		if same == True:
		    self.multi.AppendText('  Files are equivalent\n')
		    self.multi.AppendText('  Encoding %s\n'%endfile)
		    self.toencode.append(endfile)
	    else: self.toencode.append(endfile)
	else: pass

    def Encode(self):
	if len(self.toencode) > 0:
	    compressfile = self.toencode.pop(0)
	    self.multi.AppendText('Encoding %s\n'%compressfile)
	    self.LameTrack(compressfile)

    def LameTrack(self,filename):
	args = ['lame']+self.parent.CONFIG.encoder_opts.split(' ')
	# Add artist info etc here

	artist = self.parent.artist.GetValue()
	track = self.parent.grid.GetCellValue(self.curtrk-1,0)
	number = '%0.2d'%self.curtrk
	album = self.parent.title.GetValue()
	year = self.parent.year.GetValue()
	
	if '--ta' in self.parent.CONFIG.encoder_opts:
	    args.append('--ta')
	    args.append(artist)
	if '--tt' in self.parent.CONFIG.encoder_opts:
	    args.append('--tt')
	    args.append(track)
	if '--tn' in self.parent.CONFIG.encoder_opts:
	    args.append('--tn')
	    args.append(number)
	if '--tl' in self.parent.CONFIG.encoder_opts:
	    args.append('--tl')
	    args.append(album)
	if '--ty' in self.parent.CONFIG.encoder_opts:
	    args.append('--ty')
	    args.append(year)

	path = self.parent.CONFIG.basedir
	args.append(os.path.join(path,filename))

	outfile = copy(self.parent.CONFIG.file_fmt)
	outfile = self.GetName(outfile)
	args.append(os.path.join(path,outfile+'.mp3')) # Make this follow defined convention
	self.p = sub.Popen(args,-1,shell=False)

    def GetName(self,outfile):
	outfile = outfile.replace('[a]',self.parent.artist.GetValue())
	outfile = outfile.replace('[n]','%0.2d'%self.curtrk)
	outfile = outfile.replace('[t]',self.parent.grid.GetCellValue(self.curtrk-1,0))
	outfile = outfile.replace('[y]',self.parent.year.GetValue())
	return outfile

    def CheckTemps(self,curtrk):
	path = self.parent.CONFIG.basedir
	endfile = os.path.join(path,'temp%d_%d.wav'%(curtrk,self.parent.CONFIG.nscans-1))
	return os.path.exists(endfile)

    def RemoveTemps(self,curtrk):
	self.multi.AppendText('  Removing temp files for Track %d\n'%curtrk)
	path = self.parent.CONFIG.basedir
	for i in range(self.parent.CONFIG.nscans):
	    filename = os.path.join(path,'temp%d_%d.wav'%(curtrk,i))
	    os.system('rm %s'%filename)

    def Halt(self,event):
	self.ExtractEnable()
	if hasattr(self.p,'kill'): self.p.kill()
	self.timer.Stop()

    def WriteLog(self):
	artist = self.parent.artist.GetValue()
	album = self.parent.title.GetValue()
	filename = '%s - %s.log'%(artist,album)
	fh = open(os.path.join(self.parent.CONFIG.basedir,filename),'w')
	fh.writelines(self.multi.GetValue())
	fh.close()

    def Close(self,event): print 'Close'



class ExtractMenu(wx.Frame):
    def __init__(self,parent):
	frmsty = wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER|wx.RESIZE_BOX|wx.MAXIMIZE_BOX|wx.CLOSE_BOX)
        wx.Frame.__init__(self, parent, -1, title="Extracting...",size=(850,600),style=frmsty)

        p = wx.Panel(self)
        nb = wx.Notebook(p)
	self.nb = nb
	page1 = ExtractMain(nb,parent)
        page2 = PageTwo(nb)

        nb.AddPage(page1, " Main ")
        nb.AddPage(page2, "Page 2")

        sizer = wx.BoxSizer()
        sizer.Add(nb, 1, wx.EXPAND)
        p.SetSizer(sizer)
	self.Show()

class PrefsMain(wx.Panel):
    def __init__(self, nb, parent):
        wx.Panel.__init__(self, nb)
	sizer = wx.FlexGridSizer(4, 1, 0, 0)

	devicetxt = wx.StaticText(self,-1,'Device')
	device = wx.TextCtrl(self,-1,'/dev/cdrom')
	device.SetMinSize((200,27))
	devbox = wx.FlexGridSizer(1,2,0,0)
	devbox.Add(devicetxt, 1, wx.ALL, 10)
	devbox.Add(device, 1, wx.ALL, 5)
	self.__setattr__('device',device)

	offsettxt = wx.StaticText(self,-1,'Offset')
	offset = wx.SpinCtrl(self,-1,'0',min=0,max=10000)
	eject_after = wx.CheckBox(self,-1,'Eject after extraction')
	offbox = wx.FlexGridSizer(1,3,0,0)
	offbox.Add(offsettxt, 1, wx.ALL, 10)
	offbox.Add(offset, 1, wx.ALL, 5)
	offbox.Add(eject_after, 1, wx.ALL, 10)
	self.__setattr__('offset',offset)
	self.__setattr__('eject_after',eject_after)

	outputtxt = wx.StaticText(self,-1,'Output Format')
	output = wx.TextCtrl(self,-1,'[a] - [n] [t]')
	output.SetMinSize((200,27))
	outputbox = wx.FlexGridSizer(1,2,0,0)
	outputbox.Add(outputtxt, 1, wx.ALL, 10)
	outputbox.Add(output, 1, wx.ALL, 5)
	self.__setattr__('file_fmt',output)

	outex = wx.StaticText(self,-1,'[a] = Artist, [n] = Number, [t] = Track Name, [y] = Year')
	outexbox = wx.FlexGridSizer(1,1,0,0)
	outexbox.Add(outex, 1, wx.LEFT, 25)

	bdirtxt = wx.StaticText(self,-1,'Base Directory')
	self.bdir = wx.TextCtrl(self,-1,os.path.join(os.environ.get('HOME'),'Music'))
	self.bdir.SetMinSize((185,27))
	browse = wx.Button(self,-1,'Browse')
	browse.SetMinSize((68,33))
	bdirbox = wx.FlexGridSizer(1,3,0,0)
	bdirbox.Add(bdirtxt, 1, wx.ALL, 10)
	bdirbox.Add(self.bdir, 1, wx.ALL, 5)
	bdirbox.Add(browse, 1, wx.ALL, 2)
	self.__setattr__('basedir',self.bdir)

	nscanstxt = wx.StaticText(self,-1,'#Scans')
	nscans = wx.SpinCtrl(self,-1,'2',min=1,max=5)
	nrescanstxt = wx.StaticText(self,-1,'#Rescans')
	nrescans = wx.SpinCtrl(self,-1,'0',min=0,max=10)
	nscanbox = wx.FlexGridSizer(1,4,0,0)
	nscanbox.Add(nscanstxt, 1, wx.ALL, 10)
	nscanbox.Add(nscans, 1, wx.ALL, 5)
	nscanbox.Add(nrescanstxt, 1, wx.ALL, 10)
	nscanbox.Add(nrescans, 1, wx.ALL, 5)
	self.__setattr__('nscans',nscans)
	self.__setattr__('nrescans',nrescans)

	radioList = [' lame   ',' flac   ',' wav   ']
	radio = wx.RadioBox(self,-1,'Output Type ',choices=radioList,majorDimension = 3,style = wx.RA_SPECIFY_COLS)
	radiologbox = wx.FlexGridSizer(1,2,0,0)
	radiologbox.Add(radio, 1, wx.LEFT, 15)
	logfile = wx.CheckBox(self,-1,'Save Log File')
	logfile.SetValue(True)
	radiologbox.Add(logfile, 1, wx.ALL, 15)
	self.__setattr__('encoding',radio)
	self.__setattr__('logfile',logfile)

	sizer.Add(devbox,1,wx.TOP,25)
	sizer.Add(offbox,1,wx.ALL,10)
	sizer.Add(outputbox,1,wx.TOP,15)
	sizer.Add(outexbox,1,wx.TOP,0)
	sizer.Add(bdirbox,1,wx.TOP,30)
	sizer.Add(nscanbox,1,wx.TOP,20)
	sizer.Add(radiologbox,1,wx.TOP,20)

	self.SetSizer(sizer)
	browse.Bind(wx.EVT_BUTTON,self.Browse)
	
	#logfile
	#compression algorithm

    def Browse(self,event):
	dlg = wx.DirDialog(self, 'Choose a file', self.bdir.GetValue(), wx.OPEN)
	if dlg.ShowModal() == wx.ID_OK:
		self.bdir.SetValue(dlg.GetPath())

class PrefsLame(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
	sizer = wx.FlexGridSizer(5, 1, 0, 0)
	self.opts = {}
	radioList = ['Use Options','Command Line ']
	radio = wx.RadioBox(self,-1,'Select',choices=radioList,majorDimension = 2,style = wx.RA_SPECIFY_ROWS)
	radiobox = wx.FlexGridSizer(1,1,0,0)
	radiobox.Add(radio, 1, wx.LEFT, 10)

	comptxt = wx.StaticText(self,-1,'Compression')
	comptype = wx.Choice(self,-1,choices=['VBR','CBR'])
	self.opts['compression'] = comptype
	comptype.SetMinSize((70,27))
	qualtxt = wx.StaticText(self,-1,'Quality')
	self.vbrchoices = ['0 (highest)','1','2','3','4','5','6 (lowest)']
	self.cbrchoices = ['320','256','192','160','128']
	qualtype = wx.Choice(self,-1,choices=self.vbrchoices)
	self.opts['quality'] = qualtype
	qualtype.SetMinSize((110,27))
	compbox = wx.FlexGridSizer(1,4,0,0)
	compbox.Add(comptxt, 1, wx.ALL, 10)
	compbox.Add(comptype, 1, wx.ALL|wx.ADJUST_MINSIZE, 5)
	compbox.Add(qualtxt, 1, wx.ALL, 10)
	compbox.Add(qualtype, 1, wx.ALL|wx.ADJUST_MINSIZE, 5)

	id3tag = wx.CheckBox(self,-1,'Include id3 Tags')
	self.opts['id3'] = id3tag
	id3tag.SetValue(True)
	id3box = wx.FlexGridSizer(1,1,0,0)
	id3box.Add(id3tag, 1, wx.ALL, 10)

	artist = wx.CheckBox(self,-1,'Artist ')
	self.opts['artist'] = artist
	artist.SetValue(True)
	number = wx.CheckBox(self,-1,'Number ')
	self.opts['number'] = number
	number.SetValue(True)
	track = wx.CheckBox(self,-1,'Track ')
	self.opts['track'] = track
	track.SetValue(True)
	year = wx.CheckBox(self,-1,'Year ')
	self.opts['year'] = year
	year.SetValue(True)
	album = wx.CheckBox(self,-1,'Album ')
	self.opts['album'] = album
	album.SetValue(True)
	id3valbox = wx.FlexGridSizer(1,5,0,0)
	id3valbox.Add(artist, 1, wx.LEFT, 35)
	id3valbox.Add(track, 1, wx.LEFT, 5)
	id3valbox.Add(album, 1, wx.LEFT, 5)
	id3valbox.Add(number, 1, wx.LEFT, 5)
	id3valbox.Add(year, 1, wx.LEFT, 5)

	cmdlinetxt = wx.StaticText(self,-1,'Command Line')
	cmdline = wx.TextCtrl(self,-1,'')
	self.__setattr__('cmdline',cmdline)
	cmdline.SetMinSize((250,27))
	cmdbox = wx.FlexGridSizer(1,2,0,0)
	cmdbox.Add(cmdlinetxt, 1, wx.ALL, 10)
	cmdbox.Add(cmdline, 1, wx.ALL, 5)
	cmdline.Disable()

	sizer.Add(radiobox,1,wx.TOP,15)
	sizer.Add(compbox,1,wx.ALL,10)
	sizer.Add(id3box,1,wx.TOP,0)
	sizer.Add(id3valbox,1,wx.TOP,0)
	sizer.Add(cmdbox,1,wx.TOP,50)


	radio.Bind(wx.EVT_RADIOBOX,self.RadioClick)
	comptype.Bind(wx.EVT_CHOICE,self.CompChoice)
	id3tag.Bind(wx.EVT_CHECKBOX,self.ID3Select)
	qualtype.Bind(wx.EVT_CHOICE,self.MakeCmd)
	artist.Bind(wx.EVT_CHECKBOX,self.MakeCmd)
	track.Bind(wx.EVT_CHECKBOX,self.MakeCmd)
	year.Bind(wx.EVT_CHECKBOX,self.MakeCmd)
	number.Bind(wx.EVT_CHECKBOX,self.MakeCmd)
	album.Bind(wx.EVT_CHECKBOX,self.MakeCmd)
	self.SetSizer(sizer)
	self.MakeCmd(None)

    def RadioClick(self,event):
	radioBox = event.GetEventObject()
	radioIndex = radioBox.GetSelection()
	if radioIndex == 0:
	    for i in self.opts.keys(): 
		self.opts[i].Enable()
	    self.cmdline.Disable()
	    self.MakeCmd(None)
	else:
	    for i in self.opts.keys():
		self.opts[i].Disable()
	    self.cmdline.Enable()

    def CompChoice(self,event):
	val = self.opts['compression'].GetStringSelection()
	if val == 'VBR': 
	    self.opts['quality'].SetItems(self.vbrchoices)
	    self.opts['quality'].SetSelection(0)
	else:
	    self.opts['quality'].SetItems(self.cbrchoices)
	    self.opts['quality'].SetSelection(0)
	self.MakeCmd(None)

    def ID3Select(self,event):
	id3tag = event.GetEventObject()
	val = id3tag.GetValue()
	if val:
	    self.opts['artist'].Enable()
	    self.opts['track'].Enable()
	    self.opts['number'].Enable()
	    self.opts['year'].Enable()
	    self.opts['album'].Enable()
	else:
	    self.opts['artist'].Disable()
	    self.opts['track'].Disable()
	    self.opts['number'].Disable()
	    self.opts['year'].Disable()
	    self.opts['album'].Disable()
	self.MakeCmd(None)


    def MakeCmd(self,event):
	cmd = []
	compression = self.opts['compression'].GetStringSelection()
	if compression == 'VBR': cmd.append('-V')
	else: cmd.append('-b')
	cmd.append(self.opts['quality'].GetStringSelection().split(' ')[0])
	if self.opts['id3'].GetValue():
	    cmd.append('--add-id3v2')
	    if self.opts['artist'].GetValue(): cmd.append('--ta %a')
	    if self.opts['track'].GetValue(): cmd.append('--tt %t')
	    if self.opts['album'].GetValue(): cmd.append('--tl %l')
	    if self.opts['number'].GetValue(): cmd.append('--tn %n')
	    if self.opts['year'].GetValue(): cmd.append('--ty %y')
	self.cmdline.SetValue('')
	for i in cmd: self.cmdline.AppendText(i+' ')

class PrefsFlac(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
	sizer = wx.FlexGridSizer(5, 1, 0, 0)
	self.opts = {}
	radioList = ['Use Options','Command Line ']
	radio = wx.RadioBox(self,-1,'Select',choices=radioList,majorDimension = 2,style = wx.RA_SPECIFY_ROWS)
	radiobox = wx.FlexGridSizer(1,1,0,0)
	radiobox.Add(radio, 1, wx.LEFT, 10)

	comptxt = wx.StaticText(self,-1,'Compression Level')
	flacchoices = ['0 (fastest)','1','2','3','4','5','6','7','8 (slowest)']
	comptype = wx.Choice(self,-1,choices=flacchoices)
	comptype.SetMinSize((120,27))
	verify = wx.CheckBox(self,-1,'Verify ')
	self.opts['compression'] = comptype
	self.opts['verify'] = verify
	compbox = wx.FlexGridSizer(1,3,0,0)
	compbox.Add(comptxt, 1, wx.ALL, 10)
	compbox.Add(comptype, 1, wx.ALL|wx.ADJUST_MINSIZE, 5)
	compbox.Add(verify, 1, wx.ALL, 10)

	idtag = wx.CheckBox(self,-1,'Include Tags')
	self.opts['id'] = idtag
	idtag.SetValue(True)
	idbox = wx.FlexGridSizer(1,1,0,0)
	idbox.Add(idtag, 1, wx.ALL, 10)

	artist = wx.CheckBox(self,-1,'Artist ')
	self.opts['artist'] = artist
	artist.SetValue(True)
	number = wx.CheckBox(self,-1,'Number ')
	self.opts['number'] = number
	number.SetValue(True)
	track = wx.CheckBox(self,-1,'Track ')
	self.opts['track'] = track
	track.SetValue(True)
	year = wx.CheckBox(self,-1,'Year ')
	self.opts['year'] = year
	year.SetValue(True)
	album = wx.CheckBox(self,-1,'Album ')
	self.opts['album'] = album
	album.SetValue(True)
	idvalbox = wx.FlexGridSizer(1,5,0,0)
	idvalbox.Add(artist, 1, wx.LEFT, 35)
	idvalbox.Add(track, 1, wx.LEFT, 5)
	idvalbox.Add(album, 1, wx.LEFT, 5)
	idvalbox.Add(number, 1, wx.LEFT, 5)
	idvalbox.Add(year, 1, wx.LEFT, 5)

	cmdlinetxt = wx.StaticText(self,-1,'Command Line')
	cmdline = wx.TextCtrl(self,-1,'')
	self.__setattr__('cmdline',cmdline)
	cmdline.SetMinSize((250,27))
	cmdbox = wx.FlexGridSizer(1,2,0,0)
	cmdbox.Add(cmdlinetxt, 1, wx.ALL, 10)
	cmdbox.Add(cmdline, 1, wx.ALL, 5)
	cmdline.Disable()

	sizer.Add(radiobox,1,wx.TOP,15)
	sizer.Add(compbox,1,wx.ALL,10)
	sizer.Add(idbox,1,wx.TOP,0)
	sizer.Add(idvalbox,1,wx.TOP,0)
	sizer.Add(cmdbox,1,wx.TOP,50)


	radio.Bind(wx.EVT_RADIOBOX,self.RadioClick)
	comptype.Bind(wx.EVT_CHOICE,self.MakeCmd)
	idtag.Bind(wx.EVT_CHECKBOX,self.IDSelect)
	verify.Bind(wx.EVT_CHECKBOX,self.MakeCmd)
	artist.Bind(wx.EVT_CHECKBOX,self.MakeCmd)
	track.Bind(wx.EVT_CHECKBOX,self.MakeCmd)
	year.Bind(wx.EVT_CHECKBOX,self.MakeCmd)
	number.Bind(wx.EVT_CHECKBOX,self.MakeCmd)
	album.Bind(wx.EVT_CHECKBOX,self.MakeCmd)
	self.SetSizer(sizer)
	self.MakeCmd(None)

    def RadioClick(self,event):
	radioBox = event.GetEventObject()
	radioIndex = radioBox.GetSelection()
	if radioIndex == 0:
	    for i in self.opts.keys(): 
		self.opts[i].Enable()
	    self.cmdline.Disable()
	    self.MakeCmd(None)
	else:
	    for i in self.opts.keys():
		self.opts[i].Disable()
	    self.cmdline.Enable()

    def IDSelect(self,event):
	idtag = event.GetEventObject()
	val = idtag.GetValue()
	if val:
	    self.opts['artist'].Enable()
	    self.opts['track'].Enable()
	    self.opts['number'].Enable()
	    self.opts['year'].Enable()
	    self.opts['album'].Enable()
	else:
	    self.opts['artist'].Disable()
	    self.opts['track'].Disable()
	    self.opts['number'].Disable()
	    self.opts['year'].Disable()
	    self.opts['album'].Disable()
	self.MakeCmd(None)


    def MakeCmd(self,event):
	cmd = []
	cmd.append('-'+self.opts['compression'].GetStringSelection().split(' ')[0])
	if self.opts['verify'].GetValue(): cmd.append('-V')
	if self.opts['id'].GetValue():
	    if self.opts['artist'].GetValue(): cmd.append('-T \"artist=%a\"')
	    if self.opts['track'].GetValue(): cmd.append('-T \"title=%t\"')
	    if self.opts['album'].GetValue(): cmd.append('-T \"album=%l\"')
	    if self.opts['number'].GetValue(): cmd.append('-T \"tracknumber=%n\"')
	    if self.opts['year'].GetValue(): cmd.append('-T \"year=%y\"')
	self.cmdline.SetValue('')
	for i in cmd: self.cmdline.AppendText(i+' ')

class PrefsDevs(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        t = wx.StaticText(self, -1, "This is a PageTwo object", (40,40))


class ConfigureMenu(wx.Frame):
    def __init__(self,parent):
	frmsty = wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER|wx.RESIZE_BOX|wx.MAXIMIZE_BOX|wx.CLOSE_BOX)
        wx.Frame.__init__(self, parent, -1, title="Preferences",size=(400,500),style=frmsty)
	self.parent = parent
        p = wx.Panel(self)
	p2 = wx.Panel(p)
        nb = wx.Notebook(p)
	self.nb = nb
	self.main = PrefsMain(nb,parent)
	#page2 = PrefsDevs(nb)
        self.lame = PrefsLame(nb)
	self.flac = PrefsFlac(nb)

        nb.AddPage(self.main, " Main ")
        #nb.AddPage(page2, " Device ")
	nb.AddPage(self.lame, " Lame ")
	nb.AddPage(self.flac, " Flac ")

	applybtn = wx.Button(p,-1,'Apply')
	applybtn.SetMinSize((60,32))
	okbtn = wx.Button(p,-1,'Ok')
	okbtn.SetMinSize((60,32))
	closebtn = wx.Button(p,-1,'Close')
	closebtn.SetMinSize((60,32))

        sizer = wx.FlexGridSizer(2, 1, 0, 0)
	nb.SetMinSize((400,460))
	p2.SetMinSize((195,37))
	sizer2 = wx.FlexGridSizer(1, 4, 0, 0)
        sizer.Add(nb, 1, wx.EXPAND|wx.ADJUST_MINSIZE)
	sizer2.Add(p2, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
	sizer2.Add(applybtn,1,wx.ALL|wx.ALIGN_RIGHT,2)
	sizer2.Add(okbtn,1,wx.ALL|wx.ALIGN_RIGHT,2)
	sizer2.Add(closebtn,1,wx.ALL|wx.ALIGN_RIGHT,2)
	sizer.Add(sizer2,1,wx.ALL, 2)

        p.SetSizer(sizer)
	#self.Show()

	applybtn.Bind(wx.EVT_BUTTON,self.Apply)
	okbtn.Bind(wx.EVT_BUTTON,self.Ok)
	closebtn.Bind(wx.EVT_BUTTON,self.Close)

    def Apply(self,event):
	self.parent.CONFIG.__setattr__('encoder',self.main.encoding.GetStringSelection().strip())
	self.parent.CONFIG.__setattr__('nscans',int(self.main.nscans.GetValue()))
	self.parent.CONFIG.__setattr__('nrescans',int(self.main.nrescans.GetValue()))
	self.parent.CONFIG.__setattr__('file_fmt',self.main.file_fmt.GetValue())
	self.parent.CONFIG.__setattr__('device',self.main.device.GetValue())
	self.parent.CONFIG.__setattr__('basedir',self.main.basedir.GetValue())
	self.parent.CONFIG.__setattr__('eject_after',self.main.eject_after.GetValue())
	self.parent.CONFIG.__setattr__('logfile',self.main.logfile.GetValue())
	self.parent.CONFIG.__setattr__('offset',self.main.offset.GetValue())
	self.parent.CONFIG.__setattr__('encoder_opts',self.lame.cmdline.GetValue())
	fh = open('DxV.config','w')
	cp.dump(self.parent.CONFIG,fh)
	fh.close()

    def SetConfig(self,CONFIG):
	self.main.nscans.SetValue(int(CONFIG.nscans))
	self.main.nrescans.SetValue(int(CONFIG.nrescans))
	self.main.file_fmt.SetValue(CONFIG.file_fmt)
	self.main.device.SetValue(CONFIG.device)
	self.main.basedir.SetValue(CONFIG.basedir)
	self.main.eject_after.SetValue(CONFIG.eject_after)
	self.main.logfile.SetValue(CONFIG.logfile)
	self.main.offset.SetValue(CONFIG.offset)
	if CONFIG.encoder == 'lame': self.main.encoding.SetSelection(0)
	elif CONFIG.encoder == 'flac': self.main.encoding.SetSelection(1)
	else: self.main.encoding.SetSelection(2)
	self.lame.cmdline.SetValue(CONFIG.encoder_opts)

    def Ok(self,event):	
	self.Hide()
	self.parent.configure.SetValue(0)
    
    def Close(self,event):
	self.Hide()
	self.parent.configure.SetValue(0)

if __name__ == "__main__":
    app = wx.App()
    MainFrame().Show()
    app.MainLoop()
